#include "eigen/linear.h"

#include "eigen/normal.h"
#include "log.h"

namespace  ldl_eigen
{

Linear::Linear(int64_t d, int64_t h)
{
    m_weights = Normal::matrix(d, h, 0.0, 1.0/std::sqrt(double(h)));
    m_bias = Eigen::VectorXf::Zero(h);
    // LogInfo() << "weights:" << m_weights;
    // LogInfo() << "bias: " << bias_;

}

void Linear::forward()
{
    m_output = (*m_ptr_input * m_weights).rowwise() + m_bias.transpose();
}

void Linear::backward()
{
    m_weights_gradient = (*m_ptr_input).transpose() * (*m_ptr_output_gradient);
    m_bias_gradient = (*m_ptr_output_gradient).colwise().sum().transpose();
    m_input_gradient =  (*m_ptr_output_gradient) * m_weights.transpose();
}

void Linear::update()
{
    const double lr = 0.01;
    m_weights -= lr * m_weights_gradient;
    m_bias -= lr * m_bias_gradient;
}

Eigen::MatrixXf Linear::get_weights()
{
    return m_weights;
}
void Linear::set_weights(const Eigen::MatrixXf &weights)
{
    m_weights = weights;
}

Eigen::VectorXf Linear::get_bias()
{
    return m_bias;
}
void Linear::set_bias(const Eigen::VectorXf &bias)
{
    m_bias = bias;
}

}
